#include <Databases/DatabaseOnDisk.h>
#include <Storages/System/attachInformationSchemaTables.h>
#include <Storages/System/attachSystemTablesImpl.h>
#include <Parsers/ParserCreateQuery.h>
#include <Parsers/parseQuery.h>

namespace DB
{

/// Below are SQL definitions for views in "information_schema". Perhaps it would be more aesthetic to have them in .sql files
/// and embed them here instead. In fact, it has been that way using INCBIN macros until #54773. The problem was that when
/// existing .sql files were changed, the build system did not recognize that this source (.cpp) file changed and instead used
/// cached object files from previous builds.
///
/// INCBIN is one of many libraries to embed external data. We might wait a little bit longer and try #embed (*) which should
/// solve the problem once and for all after 40 years.
///
/// (*) https://thephd.dev/finally-embed-in-c23

static constexpr std::string_view schemata = R"(
    ATTACH VIEW schemata
    (
        `catalog_name` String,
        `schema_name` String,
        `schema_owner` String,
        `default_character_set_catalog` Nullable(String),
        `default_character_set_schema` Nullable(String),
        `default_character_set_name` Nullable(String),
        `default_collation_name` Nullable(String),
        `sql_path` Nullable(String),
        `CATALOG_NAME` String,
        `SCHEMA_NAME` String,
        `SCHEMA_OWNER` String,
        `DEFAULT_CHARACTER_SET_CATALOG` Nullable(String),
        `DEFAULT_CHARACTER_SET_SCHEMA` Nullable(String),
        `DEFAULT_CHARACTER_SET_NAME` Nullable(String),
        `DEFAULT_COLLATION_NAME` Nullable(String),
        `SQL_PATH` Nullable(String)
    ) AS
    SELECT
        name                          AS catalog_name,
        name                          AS schema_name,
        'default'                     AS schema_owner,
        NULL                          AS default_character_set_catalog,
        NULL                          AS default_character_set_schema,
        'utf8mb4'                     AS default_character_set_name,
        'utf8mb4_0900_ai_ci'          AS default_collation_name,
        NULL                          AS sql_path,
        catalog_name                  AS CATALOG_NAME,
        schema_name                   AS SCHEMA_NAME,
        schema_owner                  AS SCHEMA_OWNER,
        default_character_set_catalog AS DEFAULT_CHARACTER_SET_CATALOG,
        default_character_set_schema  AS DEFAULT_CHARACTER_SET_SCHEMA,
        default_character_set_name    AS DEFAULT_CHARACTER_SET_NAME,
        default_collation_name        AS DEFAULT_COLLATION_NAME,
        sql_path                      AS SQL_PATH
    FROM system.databases
)";

static constexpr std::string_view tables = R"(
    ATTACH VIEW tables
    (
        `table_catalog` String,
        `table_schema` String,
        `table_name` String,
        `table_type` String,
        `engine` Nullable(String),
        `version` Nullable(String),
        `row_format` Nullable(String),
        `table_rows` Nullable(UInt64),
        `avg_row_length` Nullable(UInt64),
        `data_length` Nullable(UInt64),
        `max_data_length` Nullable(UInt64),
        `index_length` Nullable(UInt64),
        `data_free` Nullable(UInt64),
        `auto_increment` Nullable(UInt64),
        `create_time` Nullable(DateTime),
        `update_time` Nullable(DateTime),
        `check_time` Nullable(DateTime),
        `checksum` Nullable(UInt64),
        `table_collation` Nullable(String),
        `table_comment` String,
        `create_options` Nullable(String),
        `TABLE_CATALOG` String,
        `TABLE_SCHEMA` String,
        `TABLE_NAME` String,
        `TABLE_TYPE` String,
        `ENGINE` Nullable(String),
        `VERSION` Nullable(String),
        `ROW_FORMAT` Nullable(String),
        `TABLE_ROWS` Nullable(UInt64),
        `AVG_ROW_LENGTH` Nullable(UInt64),
        `DATA_LENGTH` Nullable(UInt64),
        `MAX_DATA_LENGTH` Nullable(UInt64),
        `INDEX_LENGTH` Nullable(UInt64),
        `DATA_FREE` Nullable(UInt64),
        `AUTO_INCREMENT` Nullable(UInt64),
        `CREATE_TIME` Nullable(DateTime),
        `UPDATE_TIME` Nullable(DateTime),
        `CHECK_TIME` Nullable(DateTime),
        `CHECKSUM` Nullable(UInt64),
        `TABLE_COLLATION` Nullable(String),
        `TABLE_COMMENT` String,
        `CREATE_OPTIONS` Nullable(String)
    ) AS
    SELECT
        'def'             AS table_catalog,
        T.database             AS table_schema,
        T.name                 AS table_name,
        multiIf(any(T.is_temporary), 'LOCAL TEMPORARY',
                any(T.engine) LIKE '%View',   'VIEW',
                any(T.engine) LIKE 'System%', 'SYSTEM VIEW',
                'BASE TABLE'
                )            AS table_type,
        any(T.engine)        AS engine,
        NULL                 AS version,
        NULL                 AS row_format,
        sum(rows_count)      AS table_rows,
        intDiv(data_length, table_rows)  AS avg_row_length,
        sum(bytes_on_disk)   AS data_length,
        NULL                 AS max_data_length,
        0                    AS index_length,
        NULL                 AS data_free,
        NULL                 AS auto_increment,
        NULL                 AS create_time,
        NULL                 AS update_time,
        NULL                 AS check_time,
        NULL                 AS checksum,
        'utf8mb4_0900_ai_ci' AS table_collation,
        any(T.comment)       AS table_comment,
        NULL                 AS create_options,
        table_catalog        AS TABLE_CATALOG,
        table_schema         AS TABLE_SCHEMA,
        table_name           AS TABLE_NAME,
        table_type           AS TABLE_TYPE,
        any(T.engine)        AS ENGINE,
        version              AS VERSION,
        row_format           AS ROW_FORMAT,
        table_rows           AS TABLE_ROWS,
        avg_row_length       AS AVG_ROW_LENGTH,
        data_length          AS DATA_LENGTH,
        max_data_length      AS MAX_DATA_LENGTH,
        index_length         AS INDEX_LENGTH,
        data_free            AS DATA_FREE,
        auto_increment       AS AUTO_INCREMENT,
        create_time          AS CREATE_TIME,
        update_time          AS UPDATE_TIME,
        check_time           AS CHECK_TIME,
        checksum             AS CHECKSUM,
        table_collation      AS TABLE_COLLATION,
        table_comment        AS TABLE_COMMENT,
        create_options       AS CREATE_OPTIONS
    FROM system.tables as T
    LEFT OUTER JOIN (select * from system.cnch_parts where visible = 1) as P
        on T.database = P.database and T.name = P.table
    GROUP BY table_schema, table_name
    SETTINGS enable_multiple_tables_for_cnch_parts=1, join_use_nulls=1;
)";

static constexpr std::string_view views = R"(
    ATTACH VIEW views
    (
        `table_catalog` String,
        `table_schema` String,
        `table_name` String,
        `view_definition` String,
        `check_option` String,
        `definer` String,
        `security_type` String,
        `character_set_client` String,
        `collation_connection` String,
        `is_updatable` Enum8('NO' = 0, 'YES' = 1),
        `is_insertable_into` Enum8('NO' = 0, 'YES' = 1),
        `is_trigger_updatable` Enum8('NO' = 0, 'YES' = 1),
        `is_trigger_deletable` Enum8('NO' = 0, 'YES' = 1),
        `is_trigger_insertable_into` Enum8('NO' = 0, 'YES' = 1),
        `TABLE_CATALOG` String,
        `TABLE_SCHEMA` String,
        `TABLE_NAME` String,
        `VIEW_DEFINITION` String,
        `CHECK_OPTION` String,
        `DEFINER` String,
        `SECURITY_TYPE` String,
        `CHARACTER_SET_CLIENT` String,
        `COLLATION_CONNECTION` String,
        `IS_UPDATABLE` Enum8('NO' = 0, 'YES' = 1),
        `IS_INSERTABLE_INTO` Enum8('NO' = 0, 'YES' = 1),
        `IS_TRIGGER_UPDATABLE` Enum8('NO' = 0, 'YES' = 1),
        `IS_TRIGGER_DELETABLE` Enum8('NO' = 0, 'YES' = 1),
        `IS_TRIGGER_INSERTABLE_INTO` Enum8('NO' = 0, 'YES' = 1)
    ) AS
    SELECT
        'def' AS table_catalog,
        database AS table_schema,
        name AS table_name,
        as_select AS view_definition,
        'NONE' AS check_option,
        '' as definer,
        '' as security_type,
        'utf8mb4' as character_set_client,
        'utf8mb4_0900_ai_ci' as collation_connection,
        0 AS is_updatable,
        engine = 'MaterializedView' AS is_insertable_into,
        0 AS is_trigger_updatable,
        0 AS is_trigger_deletable,
        0 AS is_trigger_insertable_into,
        table_catalog AS TABLE_CATALOG,
        table_schema AS TABLE_SCHEMA,
        table_name AS TABLE_NAME,
        view_definition AS VIEW_DEFINITION,
        check_option AS CHECK_OPTION,
        definer AS DEFINER,
        security_type AS SECURITY_TYPE,
        character_set_client AS CHARACTER_SET_CLIENT,
        collation_connection AS COLLATION_CONNECTION,
        is_updatable AS IS_UPDATABLE,
        is_insertable_into AS IS_INSERTABLE_INTO,
        is_trigger_updatable AS IS_TRIGGER_UPDATABLE,
        is_trigger_deletable AS IS_TRIGGER_DELETABLE,
        is_trigger_insertable_into AS IS_TRIGGER_INSERTABLE_INTO
    FROM system.tables
    WHERE engine LIKE '%View'
)";

static constexpr std::string_view columns = R"(
    ATTACH VIEW columns
    (
        `table_catalog` String,
        `table_schema` String,
        `table_name` String,
        `column_name` String,
        `ordinal_position` UInt64,
        `column_default` String,
        `is_nullable` String,
        `data_type` String,
        `character_maximum_length` Nullable(UInt64),
        `character_octet_length` Nullable(UInt64),
        `numeric_precision` Nullable(UInt64),
        `numeric_precision_radix` Nullable(UInt64),
        `numeric_scale` Nullable(UInt64),
        `datetime_precision` Nullable(UInt64),
        `character_set_catalog` Nullable(String),
        `character_set_schema` Nullable(String),
        `character_set_name` Nullable(String),
        `collation_catalog` Nullable(String),
        `collation_schema` Nullable(String),
        `collation_name` Nullable(String),
        `domain_catalog` Nullable(String),
        `domain_schema` Nullable(String),
        `domain_name` Nullable(String),
        `column_comment` String,
        `column_type` String,
        `extra` Nullable(String),
        `privileges` Nullable(String),
        `TABLE_CATALOG` String,
        `TABLE_SCHEMA` String,
        `TABLE_NAME` String,
        `COLUMN_NAME` String,
        `ORDINAL_POSITION` UInt64,
        `COLUMN_DEFAULT` String,
        `IS_NULLABLE` String,
        `DATA_TYPE` String,
        `CHARACTER_MAXIMUM_LENGTH` Nullable(UInt64),
        `CHARACTER_OCTET_LENGTH` Nullable(UInt64),
        `NUMERIC_PRECISION` Nullable(UInt64),
        `NUMERIC_PRECISION_RADIX` Nullable(UInt64),
        `NUMERIC_SCALE` Nullable(UInt64),
        `DATETIME_PRECISION` Nullable(UInt64),
        `CHARACTER_SET_CATALOG` Nullable(String),
        `CHARACTER_SET_SCHEMA` Nullable(String),
        `CHARACTER_SET_NAME` Nullable(String),
        `COLLATION_CATALOG` Nullable(String),
        `COLLATION_SCHEMA` Nullable(String),
        `COLLATION_NAME` Nullable(String),
        `DOMAIN_CATALOG` Nullable(String),
        `DOMAIN_SCHEMA` Nullable(String),
        `DOMAIN_NAME` Nullable(String),
        `COLUMN_COMMENT` String,
        `COLUMN_TYPE` String,
        `EXTRA` Nullable(String),
        `PRIVILEGES` Nullable(String)
    ) AS
    SELECT
        'def' AS table_catalog,
        database AS table_schema,
        table AS table_name,
        name AS column_name,
        position AS ordinal_position,
        default_expression AS column_default,
        type LIKE 'Nullable(%)' AS is_nullable,
        convertToDialectDataType(type) AS data_type,
        character_octet_length AS character_maximum_length,
        character_octet_length,
        numeric_precision,
        numeric_precision_radix,
        numeric_scale,
        datetime_precision,
        NULL AS character_set_catalog,
        NULL AS character_set_schema,
        'utf8mb4' AS character_set_name,
        NULL AS collation_catalog,
        NULL AS collation_schema,
        'utf8mb4_0900_ai_ci' AS collation_name,
        NULL AS domain_catalog,
        NULL AS domain_schema,
        NULL AS domain_name,
        comment AS column_comment,
        convertToDialectColumnType(type) AS column_type,
        NULL AS extra,
        NULL AS privileges,
        table_catalog AS TABLE_CATALOG,
        table_schema AS TABLE_SCHEMA,
        table_name AS TABLE_NAME,
        column_name AS COLUMN_NAME,
        ordinal_position AS ORDINAL_POSITION,
        column_default AS COLUMN_DEFAULT,
        is_nullable AS IS_NULLABLE,
        data_type AS DATA_TYPE,
        character_maximum_length AS CHARACTER_MAXIMUM_LENGTH,
        character_octet_length AS CHARACTER_OCTET_LENGTH,
        numeric_precision AS NUMERIC_PRECISION,
        numeric_precision_radix AS NUMERIC_PRECISION_RADIX,
        numeric_scale AS NUMERIC_SCALE,
        datetime_precision AS DATETIME_PRECISION,
        character_set_catalog AS CHARACTER_SET_CATALOG,
        character_set_schema AS CHARACTER_SET_SCHEMA,
        character_set_name AS CHARACTER_SET_NAME,
        collation_catalog AS COLLATION_CATALOG,
        collation_schema AS COLLATION_SCHEMA,
        collation_name AS COLLATION_NAME,
        domain_catalog AS DOMAIN_CATALOG,
        domain_schema AS DOMAIN_SCHEMA,
        domain_name AS DOMAIN_NAME,
        column_comment AS COLUMN_COMMENT,
        column_type AS COLUMN_TYPE,
        extra AS EXTRA,
        privileges AS PRIVILEGES
    FROM system.columns
)";

static constexpr std::string_view key_column_usage = R"(
    ATTACH VIEW key_column_usage
        (
         `constraint_catalog` String,
         `constraint_schema` String,
         `constraint_name` Nullable(String),
         `table_catalog` String,
         `table_schema` String,
         `table_name` String,
         `column_name` Nullable(String),
         `ordinal_position` UInt32,
         `position_in_unique_constraint` Nullable(UInt32),
         `referenced_table_schema` Nullable(String),
         `referenced_table_name` Nullable(String),
         `referenced_column_name` Nullable(String),
         `CONSTRAINT_CATALOG` Nullable(String),
         `CONSTRAINT_SCHEMA` Nullable(String),
         `CONSTRAINT_NAME` Nullable(String),
         `TABLE_CATALOG` String,
         `TABLE_SCHEMA` String,
         `TABLE_NAME` String,
         `COLUMN_NAME` Nullable(String),
         `ORDINAL_POSITION` UInt32,
         `POSITION_IN_UNIQUE_CONSTRAINT` Nullable(UInt32),
         `REFERENCED_TABLE_SCHEMA` Nullable(String),
         `REFERENCED_TABLE_NAME` Nullable(String),
         `REFERENCED_COLUMN_NAME` Nullable(String)
    ) AS
    SELECT
        'def'                         AS constraint_catalog,
        database                      AS constraint_schema,
        'PRIMARY'                     AS constraint_name,
        'def'                         AS table_catalog,
        database                      AS table_schema,
        table                         AS table_name,
        name                          AS column_name,
        1                             AS ordinal_position,
        NULL                          AS position_in_unique_constraint,
        NULL                          AS referenced_table_schema,
        NULL                          AS referenced_table_name,
        NULL                          AS referenced_column_name,
        constraint_catalog            AS CONSTRAINT_CATALOG,
        constraint_schema             AS CONSTRAINT_SCHEMA,
        constraint_name               AS CONSTRAINT_NAME,
        table_catalog                 AS TABLE_CATALOG,
        table_schema                  AS TABLE_SCHEMA,
        table_name                    AS TABLE_NAME,
        column_name                   AS COLUMN_NAME,
        ordinal_position              AS ORDINAL_POSITION,
        position_in_unique_constraint AS POSITION_IN_UNIQUE_CONSTRAINT,
        referenced_table_schema       AS REFERENCED_TABLE_SCHEMA,
        referenced_table_name         AS REFERENCED_TABLE_NAME,
        referenced_column_name        AS REFERENCED_COLUMN_NAME
    FROM system.cnch_columns
    WHERE is_in_primary_key;
)";

static constexpr std::string_view referential_constraints = R"(
    ATTACH VIEW referential_constraints
        (
         `constraint_catalog` String,
         `constraint_schema` String,
         `constraint_name` Nullable(String),
         `unique_constraint_catalog` String,
         `unique_constraint_schema` String,
         `unique_constraint_name` Nullable(String),
         `match_option` String,
         `update_rule` String,
         `delete_rule` String,
         `table_name` String,
         `referenced_table_name` String,
         `CONSTRAINT_CATALOG` String,
         `CONSTRAINT_SCHEMA` String,
         `CONSTRAINT_NAME` Nullable(String),
         `UNIQUE_CONSTRAINT_CATALOG` String,
         `UNIQUE_CONSTRAINT_SCHEMA` String,
         `UNIQUE_CONSTRAINT_NAME` Nullable(String),
         `MATCH_OPTION` String,
         `UPDATE_RULE` String,
         `DELETE_RULE` String,
         `TABLE_NAME` String,
         `REFERENCED_TABLE_NAME` String
    ) AS
    SELECT
        ''                        AS constraint_catalog,
        ''                        AS constraint_schema,
        NULL                      AS constraint_name,
        ''                        AS unique_constraint_catalog,
        NULL                      AS unique_constraint_name,
        ''                        AS unique_constraint_schema,
        ''                        AS match_option,
        ''                        AS update_rule,
        ''                        AS delete_rule,
        ''                        AS table_name,
        ''                        AS referenced_table_name,
        constraint_catalog        AS CONSTRAINT_CATALOG,
        constraint_schema         AS CONSTRAINT_SCHEMA,
        constraint_name           AS CONSTRAINT_NAME,
        unique_constraint_catalog AS UNIQUE_CONSTRAINT_CATALOG,
        unique_constraint_name    AS UNIQUE_CONSTRAINT_NAME,
        unique_constraint_schema  AS UNIQUE_CONSTRAINT_SCHEMA,
        match_option              AS MATCH_OPTION,
        update_rule               AS UPDATE_RULE,
        delete_rule               AS DELETE_RULE,
        table_name                AS TABLE_NAME,
        referenced_table_name     AS REFERENCED_TABLE_NAME
    WHERE false; -- make sure this view is always empty
)";

static constexpr std::string_view statistics = R"(
    ATTACH VIEW statistics
        (
        `table_catalog` String,
        `table_schema` String,
        `table_name` String,
        `non_unique` Int32,
        `index_schema` String,
        `index_name` Nullable(String),
        `seq_in_index` UInt32,
        `column_name` Nullable(String),
        `collation` Nullable(String),
        `cardinality` Nullable(Int64),
        `sub_part` Nullable(Int64),
        `packed` Nullable(String),
        `nullable` String,
        `index_type` String,
        `comment` String,
        `index_comment` String,
        `is_visible` String,
        `expression` Nullable(String),
        `TABLE_CATALOG` String,
        `TABLE_SCHEMA` String,
        `TABLE_NAME` String,
        `NON_UNIQUE` Int32,
        `INDEX_SCHEMA` String,
        `INDEX_NAME` Nullable(String),
        `SEQ_IN_INDEX` UInt32,
        `COLUMN_NAME` Nullable(String),
        `COLLATION` Nullable(String),
        `CARDINALITY` Nullable(Int64),
        `SUB_PART` Nullable(Int64),
        `PACKED` Nullable(String),
        `NULLABLE` String,
        `INDEX_TYPE` String,
        `COMMENT` String,
        `INDEX_COMMENT` String,
        `IS_VISIBLE` String,
        `EXPRESSION` Nullable(String)
    ) AS
    SELECT
        'def'            AS table_catalog,
        database      AS table_schema,
        name          AS table_name,
        1             AS non_unique,
        database      AS index_schema,
        'PRIMARY'     AS index_name,
        index_col.2 - 1     AS seq_in_index,
        index_col.1         AS column_name,
        'utf8mb4_0900_ai_ci'          AS collation,
        0             AS cardinality,
        NULL          AS sub_part,
        NULL          AS packed,
        ''            AS nullable,
        'PRIMARY'     AS index_type,
        ''            AS comment,
        ''            AS index_comment,
        ''            AS is_visible,
        NULL          AS expression,
        table_catalog AS TABLE_CATALOG,
        table_schema  AS TABLE_SCHEMA,
        table_name    AS TABLE_NAME,
        non_unique    AS NON_UNIQUE,
        index_schema  AS INDEX_SCHEMA,
        index_name    AS INDEX_NAME,
        seq_in_index  AS SEQ_IN_INDEX,
        column_name   AS COLUMN_NAME,
        collation     AS COLLATION,
        cardinality   AS CARDINALITY,
        sub_part      AS SUB_PART,
        packed        AS PACKED,
        nullable      AS NULLABLE,
        index_type    AS INDEX_TYPE,
        comment       AS COMMENT,
        index_comment AS INDEX_COMMENT,
        is_visible    AS IS_VISIBLE,
        expression    AS EXPRESSION
    FROM (
            SELECT *, arrayJoin(arrayMap((word, index) -> (trim(BOTH ' ()' FROM word), index),
                                        cast(splitByChar(',', if (isNull(primary_key1), primary_key1, sorting_key1)), 'Array(String)'),
                                        arrayEnumerate(cast(splitByChar(',', if (isNull(primary_key), primary_key, sorting_key)), 'Array(String)'))
                                        )
                                ) as index_col,
            if(startsWith(sorting_key, 'tuple'), substring(primary_key, 6), primary_key) as primary_key1,
            if(startsWith(sorting_key, 'tuple'), substring(sorting_key, 6), sorting_key) as sorting_key1
            FROM system.cnch_tables
            WHERE engine NOT LIKE '%View'
        )
    UNION ALL
    SELECT
        'def'            AS table_catalog,
        database      AS table_schema,
        table         AS table_name,
        1             AS non_unique,
        database      AS index_schema,
        name          AS index_name,
        0             AS seq_in_index,
        expr          AS column_name,
        'utf8mb4_0900_ai_ci'          AS collation,
        0             AS cardinality,
        NULL          AS sub_part,
        NULL          AS packed,
        ''            AS nullable,
        'PRIMARY'     AS index_type,
        ''            AS comment,
        ''            AS index_comment,
        ''            AS is_visible,
        NULL          AS expression,
        table_catalog AS TABLE_CATALOG,
        table_schema  AS TABLE_SCHEMA,
        table_name    AS TABLE_NAME,
        non_unique    AS NON_UNIQUE,
        index_schema  AS INDEX_SCHEMA,
        index_name    AS INDEX_NAME,
        seq_in_index  AS SEQ_IN_INDEX,
        column_name   AS COLUMN_NAME,
        collation     AS COLLATION,
        cardinality   AS CARDINALITY,
        sub_part      AS SUB_PART,
        packed        AS PACKED,
        nullable      AS NULLABLE,
        index_type    AS INDEX_TYPE,
        comment       AS COMMENT,
        index_comment AS INDEX_COMMENT,
        is_visible    AS IS_VISIBLE,
        expression    AS EXPRESSION
    FROM system.data_skipping_indices
)";

static constexpr std::string_view events = R"(
    ATTACH VIEW events
        (
        `event_catalog` String,
        `event_schema` String,
        `event_name` String,
        `definer` String,
        `time_zone` String,
        `event_body` String,
        `event_definition` Nullable(String),
        `event_type` String,
        `execute_at` Nullable(DateTime),
        `interval_value` Nullable(String),
        `interval_field` Nullable(String),
        `sql_mode` String,
        `starts` Nullable(DateTime),
        `ends` Nullable(DateTime),
        `status` String,
        `on_completion` String,
        `created` Nullable(DateTime),
        `last_altered` Nullable(DateTime),
        `last_executed` Nullable(DateTime),
        `event_comment` String,
        `originator` UInt64,
        `character_set_client` String,
        `collation_connection` String,
        `database_collation` String,
        `EVENT_CATALOG` String,
        `EVENT_SCHEMA` String,
        `EVENT_NAME` String,
        `DEFINER` String,
        `TIME_ZONE` String,
        `EVENT_BODY` String,
        `EVENT_DEFINITION` Nullable(String),
        `EVENT_TYPE` String,
        `EXECUTE_AT` Nullable(DateTime),
        `INTERVAL_VALUE` Nullable(String),
        `INTERVAL_FIELD` Nullable(String),
        `SQL_MODE` String,
        `STARTS` Nullable(DateTime),
        `ENDS` Nullable(DateTime),
        `STATUS` String,
        `ON_COMPLETION` String,
        `CREATED` Nullable(DateTime),
        `LAST_ALTERED` Nullable(DateTime),
        `LAST_EXECUTED` Nullable(DateTime),
        `EVENT_COMMENT` String,
        `ORIGINATOR` UInt64,
        `CHARACTER_SET_CLIENT` String,
        `COLLATION_CONNECTION` String,
        `DATABASE_COLLATION` String
        ) AS
    SELECT
        '' AS event_catalog,
        '' AS event_schema,
        '' AS event_name,
        '' AS definer,
        '' AS time_zone,
        '' AS event_body,
        NULL AS event_definition,
        '' AS event_type,
        NULL AS execute_at,
        NULL AS interval_value,
        NULL AS interval_field,
        '' AS sql_mode,
        NULL AS starts,
        NULL AS ends,
        '' AS status,
        '' AS on_completion,
        NULL AS created,
        NULL AS last_altered,
        NULL AS last_executed,
        '' AS event_comment,
        0 AS originator,
        'utf8mb4' AS character_set_client,
        'utf8mb4_0900_ai_ci' AS collation_connection,
        '' AS database_collation,
        '' AS EVENT_CATALOG,
        '' AS EVENT_SCHEMA,
        '' AS EVENT_NAME,
        '' AS DEFINER,
        '' AS TIME_ZONE,
        '' AS EVENT_BODY,
        NULL AS EVENT_DEFINITION,
        '' AS EVENT_TYPE,
        NULL AS EXECUTE_AT,
        NULL AS INTERVAL_VALUE,
        NULL AS INTERVAL_FIELD,
        '' AS SQL_MODE,
        NULL AS STARTS,
        NULL AS ENDS,
        '' AS STATUS,
        '' AS ON_COMPLETION,
        NULL AS CREATED,
        NULL AS LAST_ALTERED,
        NULL AS LAST_EXECUTED,
        '' AS EVENT_COMMENT,
        0 AS ORIGINATOR,
        'utf8mb4' AS CHARACTER_SET_CLIENT,
        'utf8mb4_0900_ai_ci' AS COLLATION_CONNECTION,
        '' AS DATABASE_COLLATION
    WHERE false; -- make sure this view is always empty
)";

static constexpr std::string_view routines = R"(
    ATTACH VIEW routines
        (
        `specific_name` String,
        `routine_catalog` String,
        `routine_schema` String,
        `routine_name` String,
        `routine_type` String,
        `data_type` String,
        `character_maximum_length` Nullable(Int64),
        `character_octet_length` Nullable(Int64),
        `numeric_precision` Nullable(Int64),
        `numeric_scale` Nullable(Int64),
        `datetime_precision` Nullable(Int64),
        `character_set_name` Nullable(String),
        `collation_name` Nullable(String),
        `dtd_identifier` Nullable(String),
        `routine_body` String,
        `routine_definition` Nullable(String),
        `external_name` Nullable(String),
        `external_language` Nullable(String),
        `parameter_style` String,
        `is_deterministic` String,
        `sql_data_access` String,
        `sql_path` Nullable(String),
        `security_type` String,
        `created` Nullable(DateTime),
        `last_altered` Nullable(DateTime),
        `sql_mode` String,
        `routine_comment` String,
        `definer` String,
        `character_set_client` String,
        `collation_connection` String,
        `database_collation` String,
        `SPECIFIC_NAME` String,
        `ROUTINE_CATALOG` String,
        `ROUTINE_SCHEMA` String,
        `ROUTINE_NAME` String,
        `ROUTINE_TYPE` String,
        `DATA_TYPE` String,
        `CHARACTER_MAXIMUM_LENGTH` Nullable(Int64),
        `CHARACTER_OCTET_LENGTH` Nullable(Int64),
        `NUMERIC_PRECISION` Nullable(Int64),
        `NUMERIC_SCALE` Nullable(Int64),
        `DATETIME_PRECISION` Nullable(Int64),
        `CHARACTER_SET_NAME` Nullable(String),
        `COLLATION_NAME` Nullable(String),
        `DTD_IDENTIFIER` Nullable(String),
        `ROUTINE_BODY` String,
        `ROUTINE_DEFINITION` Nullable(String),
        `EXTERNAL_NAME` Nullable(String),
        `EXTERNAL_LANGUAGE` Nullable(String),
        `PARAMETER_STYLE` String,
        `IS_DETERMINISTIC` String,
        `SQL_DATA_ACCESS` String,
        `SQL_PATH` Nullable(String),
        `SECURITY_TYPE` String,
        `CREATED` Nullable(DateTime),
        `LAST_ALTERED` Nullable(DateTime),
        `SQL_MODE` String,
        `ROUTINE_COMMENT` String,
        `DEFINER` String,
        `CHARACTER_SET_CLIENT` String,
        `COLLATION_CONNECTION` String,
        `DATABASE_COLLATION` String
    ) AS
    SELECT
        '' AS specific_name,
        '' AS routine_catalog,
        '' AS routine_schema,
        '' AS routine_name,
        '' AS routine_type,
        '' AS data_type,
        NULL AS character_maximum_length,
        NULL AS character_octet_length,
        NULL AS numeric_precision,
        NULL AS numeric_scale,
        NULL AS datetime_precision,
        'utf8mb4' AS character_set_name,
        'utf8mb4_0900_ai_ci' AS collation_name,
        NULL AS dtd_identifier,
        '' AS routine_body,
        NULL AS routine_definition,
        NULL AS external_name,
        NULL AS external_language,
        '' AS parameter_style,
        '' AS is_deterministic,
        '' AS sql_data_access,
        NULL AS sql_path,
        '' AS security_type,
        NULL AS created,
        NULL AS last_altered,
        '' AS sql_mode,
        '' AS routine_comment,
        '' AS definer,
        '' AS character_set_client,
        '' AS collation_connection,
        '' AS database_collation,
        '' AS SPECIFIC_NAME,
        '' AS ROUTINE_CATALOG,
        '' AS ROUTINE_SCHEMA,
        '' AS ROUTINE_NAME,
        '' AS ROUTINE_TYPE,
        '' AS DATA_TYPE,
        NULL AS CHARACTER_MAXIMUM_LENGTH,
        NULL AS CHARACTER_OCTET_LENGTH,
        NULL AS NUMERIC_PRECISION,
        NULL AS NUMERIC_SCALE,
        NULL AS DATETIME_PRECISION,
        'utf8mb4' AS CHARACTER_SET_NAME,
        'utf8mb4_0900_ai_ci' AS COLLATION_NAME,
        NULL AS DTD_IDENTIFIER,
        '' AS ROUTINE_BODY,
        NULL AS ROUTINE_DEFINITION,
        NULL AS EXTERNAL_NAME,
        NULL AS EXTERNAL_LANGUAGE,
        '' AS PARAMETER_STYLE,
        '' AS IS_DETERMINISTIC,
        '' AS SQL_DATA_ACCESS,
        NULL AS SQL_PATH,
        '' AS SECURITY_TYPE,
        NULL AS CREATED,
        NULL AS LAST_ALTERED,
        '' AS SQL_MODE,
        '' AS ROUTINE_COMMENT,
        '' AS DEFINER,
        '' AS CHARACTER_SET_CLIENT,
        '' AS COLLATION_CONNECTION,
        '' AS DATABASE_COLLATION
    WHERE false; -- make sure this view is always empty
)";

static constexpr std::string_view triggers = R"(
    ATTACH VIEW triggers
        (
        `trigger_catalog` String,
        `trigger_schema` String,
        `trigger_name` String,
        `event_manipulation` String,
        `event_object_catalog` String,
        `event_object_schema` String,
        `event_object_table` String,
        `action_order` Int64,
        `action_condition` Nullable(String),
        `action_statement` String,
        `action_orientation` String,
        `action_timing` String,
        `action_reference_old_table` Nullable(String),
        `action_reference_new_table` Nullable(String),
        `action_reference_old_row` String,
        `action_reference_new_row` String,
        `created` Nullable(DateTime),
        `sql_mode` String,
        `definer` String,
        `character_set_client` String,
        `collation_connection` String,
        `database_collation` String,
        `TRIGGER_CATALOG` String,
        `TRIGGER_SCHEMA` String,
        `TRIGGER_NAME` String,
        `EVENT_MANIPULATION` String,
        `EVENT_OBJECT_CATALOG` String,
        `EVENT_OBJECT_SCHEMA` String,
        `EVENT_OBJECT_TABLE` String,
        `ACTION_ORDER` Int64,
        `ACTION_CONDITION` Nullable(String),
        `ACTION_STATEMENT` String,
        `ACTION_ORIENTATION` String,
        `ACTION_TIMING` String,
        `ACTION_REFERENCE_OLD_TABLE` Nullable(String),
        `ACTION_REFERENCE_NEW_TABLE` Nullable(String),
        `ACTION_REFERENCE_OLD_ROW` String,
        `ACTION_REFERENCE_NEW_ROW` String,
        `CREATED` Nullable(DateTime),
        `SQL_MODE` String,
        `DEFINER` String,
        `CHARACTER_SET_CLIENT` String,
        `COLLATION_CONNECTION` String,
        `DATABASE_COLLATION` String
    ) AS
    SELECT
        '' AS trigger_catalog,
        '' AS trigger_schema,
        '' AS trigger_name,
        '' AS event_manipulation,
        '' AS event_object_catalog,
        '' AS event_object_schema,
        '' AS event_object_table,
        0 AS action_order,
        NULL AS action_condition,
        '' AS action_statement,
        '' AS action_orientation,
        '' AS action_timing,
        NULL AS action_reference_old_table,
        NULL AS action_reference_new_table,
        '' AS action_reference_old_row,
        '' AS action_reference_new_row,
        NULL AS created,
        '' AS sql_mode,
        '' AS definer,
        '' AS character_set_client,
        '' AS collation_connection,
        '' AS database_collation,
        '' AS TRIGGER_CATALOG,
        '' AS TRIGGER_SCHEMA,
        '' AS TRIGGER_NAME,
        '' AS EVENT_MANIPULATION,
        '' AS EVENT_OBJECT_CATALOG,
        '' AS EVENT_OBJECT_SCHEMA,
        '' AS EVENT_OBJECT_TABLE,
        0 AS ACTION_ORDER,
        NULL AS ACTION_CONDITION,
        '' AS ACTION_STATEMENT,
        '' AS ACTION_ORIENTATION,
        '' AS ACTION_TIMING,
        NULL AS ACTION_REFERENCE_OLD_TABLE,
        NULL AS ACTION_REFERENCE_NEW_TABLE,
        '' AS ACTION_REFERENCE_OLD_ROW,
        '' AS ACTION_REFERENCE_NEW_ROW,
        NULL AS CREATED,
        '' AS SQL_MODE,
        '' AS DEFINER,
        '' AS CHARACTER_SET_CLIENT,
        '' AS COLLATION_CONNECTION,
        '' AS DATABASE_COLLATION
    WHERE false; -- make sure this view is always empty
)";

static constexpr std::string_view partitions = R"(
    ATTACH VIEW partitions
        (
        `table_catalog` Nullable(String),
        `table_schema` Nullable(String),
        `table_name` Nullable(String),
        `partition_name` Nullable(String),
        `subpartition_name` Nullable(String),
        `partition_ordinal_position` Nullable(UInt64),
        `subpartition_ordinal_position` Nullable(UInt64),
        `partition_method` Nullable(String),
        `subpartition_method` Nullable(String),
        `partition_expression` Nullable(String),
        `subpartition_expression` Nullable(String),
        `partition_description` Nullable(String),
        `table_rows` Nullable(Int64),
        `data_length` Nullable(Int64),
        `avg_row_length` Nullable(Int64),
        `max_data_length` Nullable(Int64),
        `index_length` Nullable(Int64),
        `data_free` Nullable(Int64),
        `create_time` Nullable(DateTime),
        `update_time` Nullable(DateTime),
        `check_time` Nullable(DateTime),
        `checksum` Nullable(UInt64),
        `partition_comment` Nullable(String),
        `nodegroup` Nullable(Int64),
        `tablespace_name` Nullable(String),
        `TABLE_CATALOG` Nullable(String),
        `TABLE_SCHEMA` Nullable(String),
        `TABLE_NAME` Nullable(String),
        `PARTITION_NAME` Nullable(String),
        `SUBPARTITION_NAME` Nullable(String),
        `PARTITION_ORDINAL_POSITION` Nullable(UInt64),
        `SUBPARTITION_ORDINAL_POSITION` Nullable(UInt64),
        `PARTITION_METHOD` Nullable(String),
        `SUBPARTITION_METHOD` Nullable(String),
        `PARTITION_EXPRESSION` Nullable(String),
        `SUBPARTITION_EXPRESSION` Nullable(String),
        `PARTITION_DESCRIPTION` Nullable(String),
        `TABLE_ROWS` Nullable(Int64),
        `DATA_LENGTH` Nullable(Int64),
        `AVG_ROW_LENGTH` Nullable(Int64),
        `MAX_DATA_LENGTH` Nullable(Int64),
        `INDEX_LENGTH` Nullable(Int64),
        `DATA_FREE` Nullable(Int64),
        `CREATE_TIME` Nullable(DateTime),
        `UPDATE_TIME` Nullable(DateTime),
        `CHECK_TIME` Nullable(DateTime),
        `CHECKSUM` Nullable(UInt64),
        `PARTITION_COMMENT` Nullable(String),
        `NODEGROUP` Nullable(Int64),
        `TABLESPACE_NAME` Nullable(String)
    ) AS
    SELECT
        'def' AS table_catalog,
        system.cnch_parts.database AS table_schema,
        system.cnch_parts.table AS table_name,
        partition AS partition_name,
        NULL AS subpartition_name,
        NULL AS partition_ordinal_position,
        NULL AS subpartition_ordinal_position,
        'HASH' AS partition_method,
        NULL AS subpartition_method,
        system.cnch_tables.partition_key AS partition_expression,
        NULL AS subpartition_expression,
        NULL AS partition_description,
        SUM(rows_count) AS table_rows,
        -- Since there is no data_compressed_bytes column,
        -- we use bytes_on_disk instead
        SUM(bytes_on_disk) AS data_length,
        intDiv(data_length, table_rows) AS avg_row_length,
        NULL AS max_data_length,
        -- There is only marks_count column, no marks_bytes
        NULL AS index_length,
        NULL AS data_free,
        NULL AS create_time,
        MAX(commit_time) AS update_time,
        NULL AS check_time,
        NULL AS checksum,
        NULL AS partition_comment,
        NULL AS nodegroup,
        'DEFAULT' AS tablespace_name,
        table_catalog AS TABLE_CATALOG,
        table_schema AS TABLE_SCHEMA,
        table_name AS TABLE_NAME,
        partition_name AS PARTITION_NAME,
        subpartition_name AS SUBPARTITION_NAME,
        partition_ordinal_position AS PARTITION_ORDINAL_POSITION,
        subpartition_ordinal_position AS SUBPARTITION_ORDINAL_POSITION,
        partition_method AS PARTITION_METHOD,
        subpartition_method AS SUBPARTITION_METHOD,
        partition_expression AS PARTITION_EXPRESSION,
        subpartition_expression AS SUBPARTITION_EXPRESSION,
        partition_description AS PARTITION_DESCRIPTION,
        table_rows AS TABLE_ROWS,
        data_length AS DATA_LENGTH,
        avg_row_length AS AVG_ROW_LENGTH,
        max_data_length AS MAX_DATA_LENGTH,
        index_length AS INDEX_LENGTH,
        data_free AS DATA_FREE,
        create_time AS CREATE_TIME,
        update_time AS UPDATE_TIME,
        check_time AS CHECK_TIME,
        checksum AS CHECKSUM,
        partition_comment AS PARTITION_COMMENT,
        nodegroup AS NODEGROUP,
        tablespace_name AS TABLESPACE_NAME
    FROM system.cnch_parts, system.cnch_tables
    WHERE system.cnch_tables.database = system.cnch_parts.database
    AND system.cnch_tables.name = system.cnch_parts.table
    AND toInt32(system.cnch_parts.part_type) = 1 -- visible
    AND notEmpty(system.cnch_tables.partition_key)
    GROUP BY
    system.cnch_parts.partition,
    system.cnch_parts.database,
    system.cnch_parts.table,
    system.cnch_tables.partition_key SETTINGS enable_multiple_tables_for_cnch_parts=1, join_use_nulls=0;
)";

static constexpr std::string_view engines = R"(
    ATTACH VIEW engines (
        `engine` String,
        `support` Nullable(String),
        `comment` Nullable(String),
        `transactions` Nullable(String),
        `xa` Nullable(String),
        `savepoints` Nullable(String),
        `ENGINE` String,
        `SUPPORT` Nullable(String),
        `COMMENT` Nullable(String),
        `TRANSACTIONS` Nullable(String),
        `XA` Nullable(String),
        `SAVEPOINTS` Nullable(String),
        `Engine` String
    ) AS
    SELECT
    name AS engine,
    NULL AS support,
    NULL AS comment,
    NULL AS transactions,
    NULL AS xa,
    NULL AS savepoints,
    engine AS ENGINE,
    support AS SUPPORT,
    comment AS COMMENT,
    transactions AS TRANSACTIONS,
    xa AS XA,
    savepoints AS SAVEPOINTS,
    engine AS Engine
    FROM system.table_engines;
)";

static constexpr std::string_view profiling = R"(
    ATTACH VIEW profiling (
        query_id Int,
        seq Int,
        state String,
        duration Int,
        cpu_user Int,
        cpu_system Int,
        context_voluntary Int,
        context_involuntary Int,
        block_ops_in Int,
        block_ops_out Int,
        messages_sent Int,
        messages_received Int,
        page_faults_major Int,
        page_faults_minor Int,
        swaps Int,
        source_function Nullable(String),
        source_file Nullable(String),
        source_line Nullable(Int),
        QUERY_ID Int,
        SEQ Int,
        STATE String,
        DURATION Int,
        CPU_USER Int,
        CPU_SYSTEM Int,
        CONTEXT_VOLUNTARY Int,
        CONTEXT_INVOLUNTARY Int,
        BLOCK_OPS_IN Int,
        BLOCK_OPS_OUT Int,
        MESSAGES_SENT Int,
        MESSAGES_RECEIVED Int,
        PAGE_FAULTS_MAJOR Int,
        PAGE_FAULTS_MINOR Int,
        SWAPS Int,
        SOURCE_FUNCTION Nullable(String),
        SOURCE_FILE Nullable(String),
        SOURCE_LINE Nullable(Int)
    ) AS
    SELECT
    0 AS query_id,
    0 AS seq,
    '' AS state,
    0 AS duration,
    0 AS cpu_user,
    0 AS cpu_system,
    0 AS context_voluntary,
    0 AS context_involuntary,
    0 AS block_ops_in,
    0 AS block_ops_out,
    0 AS messages_sent,
    0 AS messages_received,
    0 AS page_faults_major,
    0 AS page_faults_minor,
    0 AS swaps,
    NULL AS source_function,
    NULL AS source_file,
    NULL AS source_line,
    query_id AS QUERY_ID,
    seq AS SEQ,
    state AS STATE,
    duration AS DURATION,
    cpu_user AS CPU_USER,
    cpu_system AS CPU_SYSTEM,
    context_voluntary AS CONTEXT_VOLUNTARY,
    context_involuntary AS CONTEXT_INVOLUNTARY,
    block_ops_in AS BLOCK_OPS_IN,
    block_ops_out AS BLOCK_OPS_OUT,
    messages_sent AS MESSAGES_SENT,
    messages_received AS MESSAGES_RECEIVED,
    page_faults_major AS PAGE_FAULTS_MAJOR,
    page_faults_minor AS PAGE_FAULTS_MINOR,
    swaps AS SWAPS,
    source_function AS SOURCE_FUNCTION,
    source_file AS SOURCE_FILE,
    source_line AS SOURCE_LINE
    WHERE false;
)";

static constexpr std::string_view files = R"(
    ATTACH VIEW files (
        file_id Int,
        file_name String,
        file_type String,
        tablespace_name String,
        table_catalog String,
        table_schema Nullable(String),
        table_name Nullable(String),
        logfile_group_name Nullable(String),
        logfile_group_number Nullable(Int),
        engine String,
        fulltext_keys Nullable(Int),
        deleted_rows Nullable(Int),
        update_count Nullable(Int),
        free_extents Int,
        total_extents Int,
        extent_size Int,
        initial_size Int,
        maximum_size Nullable(Int),
        autoextend_size Nullable(Int),
        creation_time Nullable(DateTime),
        last_update_time Nullable(DateTime),
        last_access_time Nullable(DateTime),
        recover_time Nullable(DateTime),
        transaction_counter Nullable(Int),
        version Nullable(Int),
        row_format Nullable(String),
        table_rows Nullable(Int),
        avg_row_length Nullable(Int),
        data_length Nullable(Int),
        max_data_length Nullable(Int),
        index_length Nullable(Int),
        data_free Nullable(Int),
        create_time Nullable(DateTime),
        update_time Nullable(DateTime),
        check_time Nullable(DateTime),
        checksum Nullable(Int),
        status String,
        extra Nullable(String),
        FILE_ID Int,
        FILE_NAME String,
        FILE_TYPE String,
        TABLESPACE_NAME String,
        TABLE_CATALOG String,
        TABLE_SCHEMA Nullable(String),
        TABLE_NAME Nullable(String),
        LOGFILE_GROUP_NAME Nullable(String),
        LOGFILE_GROUP_NUMBER Nullable(Int),
        ENGINE String,
        FULLTEXT_KEYS Nullable(Int),
        DELETED_ROWS Nullable(Int),
        UPDATE_COUNT Nullable(Int),
        FREE_EXTENTS Int,
        TOTAL_EXTENTS Int,
        EXTENT_SIZE Int,
        INITIAL_SIZE Int,
        MAXIMUM_SIZE Nullable(Int),
        AUTOEXTEND_SIZE Nullable(Int),
        CREATION_TIME Nullable(DateTime),
        LAST_UPDATE_TIME Nullable(DateTime),
        LAST_ACCESS_TIME Nullable(DateTime),
        RECOVER_TIME Nullable(DateTime),
        TRANSACTION_COUNTER Nullable(Int),
        VERSION Nullable(Int),
        ROW_FORMAT Nullable(String),
        TABLE_ROWS Nullable(Int),
        AVG_ROW_LENGTH Nullable(Int),
        DATA_LENGTH Nullable(Int),
        MAX_DATA_LENGTH Nullable(Int),
        INDEX_LENGTH Nullable(Int),
        DATA_FREE Nullable(Int),
        CREATE_TIME Nullable(DateTime),
        UPDATE_TIME Nullable(DateTime),
        CHECK_TIME Nullable(DateTime),
        CHECKSUM Nullable(Int),
        STATUS String,
        EXTRA Nullable(String)
    ) AS
    SELECT
    0 AS file_id,
    '' AS file_name,
    '' AS file_type,
    '' AS tablespace_name,
    '' AS table_catalog,
    NULL AS table_schema,
    NULL AS table_name,
    NULL AS logfile_group_name,
    NULL AS logfile_group_number,
    '' AS engine,
    NULL AS fulltext_keys,
    NULL AS deleted_rows,
    NULL AS update_count,
    0 AS free_extents,
    0 AS total_extents,
    0 AS extent_size,
    0 AS initial_size,
    NULL AS maximum_size,
    NULL AS autoextend_size,
    NULL AS creation_time,
    NULL AS last_update_time,
    NULL AS last_access_time,
    NULL AS recover_time,
    NULL AS transaction_counter,
    NULL AS version,
    NULL AS row_format,
    NULL AS table_rows,
    NULL AS avg_row_length,
    NULL AS data_length,
    NULL AS max_data_length,
    NULL AS index_length,
    NULL AS data_free,
    NULL AS create_time,
    NULL AS update_time,
    NULL AS check_time,
    NULL AS checksum,
    '' AS status,
    NULL AS extra,
    file_id AS FILE_ID,
    file_name AS FILE_NAME,
    file_type AS FILE_TYPE,
    tablespace_name AS TABLESPACE_NAME,
    table_catalog AS TABLE_CATALOG,
    table_schema AS TABLE_SCHEMA,
    table_name AS TABLE_NAME,
    logfile_group_name AS LOGFILE_GROUP_NAME,
    logfile_group_number AS LOGFILE_GROUP_NUMBER,
    engine AS ENGINE,
    fulltext_keys AS FULLTEXT_KEYS,
    deleted_rows AS DELETED_ROWS,
    update_count AS UPDATE_COUNT,
    free_extents AS FREE_EXTENTS,
    total_extents AS TOTAL_EXTENTS,
    extent_size AS EXTENT_SIZE,
    initial_size AS INITIAL_SIZE,
    maximum_size AS MAXIMUM_SIZE,
    autoextend_size AS AUTOEXTEND_SIZE,
    creation_time AS CREATION_TIME,
    last_update_time AS LAST_UPDATE_TIME,
    last_access_time AS LAST_ACCESS_TIME,
    recover_time AS RECOVER_TIME,
    transaction_counter AS TRANSACTION_COUNTER,
    version AS VERSION,
    row_format AS ROW_FORMAT,
    table_rows AS TABLE_ROWS,
    avg_row_length AS AVG_ROW_LENGTH,
    data_length AS DATA_LENGTH,
    max_data_length AS MAX_DATA_LENGTH,
    index_length AS INDEX_LENGTH,
    data_free AS DATA_FREE,
    create_time AS CREATE_TIME,
    update_time AS UPDATE_TIME,
    check_time AS CHECK_TIME,
    checksum AS CHECKSUM,
    status AS STATUS,
    extra AS EXTRA
    WHERE false;
)";


/// current only return the primary key as the constraint of a table
static constexpr std::string_view table_constraints = R"(
    ATTACH VIEW table_constraints (
        `constraint_catalog` Nullable(String),
        `constraint_schema` Nullable(String),
        `constraint_name` Nullable(String),
        `table_schema` Nullable(String),
        `table_name` Nullable(String),
        `constraint_type` Nullable(String),
        `enforced` Nullable(String),
        `CONSTRAINT_CATALOG` Nullable(String),
        `CONSTRAINT_SCHEMA` Nullable(String),
        `CONSTRAINT_NAME` Nullable(String),
        `TABLE_SCHEMA` Nullable(String),
        `TABLE_NAME` Nullable(String),
        `CONSTRAINT_TYPE` Nullable(String),
        `ENFORCED` Nullable(String)
    ) AS
    SELECT
        table_catalog AS constraint_catalog,
        table_schema AS constraint_schema,
        index_name AS constraint_name,
        table_schema AS table_schema,
        table_name AS table_name,
        index_type AS constraint_type,
        'YES' AS enforced,
        constraint_catalog AS CONSTRAINT_CATALOG,
        constraint_schema AS CONSTRAINT_SCHEMA,
        constraint_name AS CONSTRAINT_NAME,
        table_schema AS TABLE_SCHEMA,
        table_name AS TABLE_NAME,
        constraint_type AS CONSTRAINT_TYPE,
        enforced AS ENFORCED
    FROM information_schema.statistics;
)";

/// View structures are taken from http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt

static void createInformationSchemaView(ContextMutablePtr context, IDatabase & database, const String & view_name, std::string_view query)
{
    try
    {
        assert(database.getDatabaseName() == DatabaseCatalog::INFORMATION_SCHEMA ||
               database.getDatabaseName() == DatabaseCatalog::INFORMATION_SCHEMA_UPPERCASE);
        if (database.getEngineName() != "Memory")
            return;

        String metadata_resource_name = view_name + ".sql";
        if (query.empty())
            return;

        ParserCreateQuery parser;
        ASTPtr ast = parseQuery(parser, query.data(), query.data() + query.size(),
                                "Attach query from embedded resource " + metadata_resource_name,
                                DBMS_DEFAULT_MAX_QUERY_SIZE, DBMS_DEFAULT_MAX_PARSER_DEPTH);

        auto & ast_create = ast->as<ASTCreateQuery &>();
        assert(view_name == ast_create.getTableInfo().getTableName());
        ast_create.attach = false;
        StorageID table_storage_id = ast_create.getTableInfo();
        table_storage_id.database_name = database.getDatabaseName();
        ast_create.setTableInfo(table_storage_id);

        StoragePtr view = createTableFromAST(ast_create, table_storage_id.getDatabaseName(),
                                             database.getTableDataPath(ast_create), context, true).second;
        database.createTable(context, table_storage_id.getTableName(), view, ast);
        ASTPtr ast_upper = ast_create.clone();
        auto & ast_create_upper = ast_upper->as<ASTCreateQuery &>();
        Poco::toUpperInPlace(table_storage_id.table_name);
        ast_create_upper.setTableInfo(table_storage_id);
        StoragePtr view_upper = createTableFromAST(ast_create_upper, table_storage_id.getDatabaseName(),
                                             database.getTableDataPath(ast_create_upper), context, true).second;

        database.createTable(context, table_storage_id.getTableName(), view_upper, ast_upper);

    }
    catch (...)
    {
        tryLogCurrentException(__PRETTY_FUNCTION__);
    }
}

void attachInformationSchema(ContextMutablePtr context, IDatabase & information_schema_database)
{
    createInformationSchemaView(context, information_schema_database, "schemata", schemata);
    createInformationSchemaView(context, information_schema_database, "tables", tables);
    createInformationSchemaView(context, information_schema_database, "views", views);
    createInformationSchemaView(context, information_schema_database, "columns", columns);
    createInformationSchemaView(context, information_schema_database, "key_column_usage", key_column_usage);
    createInformationSchemaView(context, information_schema_database, "referential_constraints", referential_constraints);
    createInformationSchemaView(context, information_schema_database, "statistics", statistics);
    createInformationSchemaView(context, information_schema_database, "events", events);
    createInformationSchemaView(context, information_schema_database, "routines", routines);
    createInformationSchemaView(context, information_schema_database, "triggers", triggers);
    createInformationSchemaView(context, information_schema_database, "partitions", partitions);
    createInformationSchemaView(context, information_schema_database, "engines", engines);
    createInformationSchemaView(context, information_schema_database, "profiling", profiling);
    createInformationSchemaView(context, information_schema_database, "files", files);
    createInformationSchemaView(context, information_schema_database, "table_constraints", table_constraints);
}

}
